package com.aikg.kgrag_java.utils;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;


public class QueryEnvironmentDatabase {
    /**
     * 查环境数据库，返回在某时刻，某经纬度范围内的环境信息
     *
     * @param time 具体的某一时刻
     * @param area 经纬度范围，列表顺序：最大纬度，最大经度，最小纬度，最小经度
     * @param type 标记，0是气象，1是水文
     * @param sentence 原语句，用来确定要检索的字段(已删除地点字段，防止产生关键字干扰)
     * @return String数据类型
     */
    public static String SearchDataBase(String time, ArrayList<Double> area, int type, String sentence){
        if (area.get(0) == 0.0 && area.get(1) == 0.0 && area.get(2) == 0.0 && area.get(3) == 0.0 ){
            return "地理位置信息获取失败";
        }
        StringBuilder result = new StringBuilder();
        StringBuilder condition = new StringBuilder();
        if (type == 0){//气象查询
            if (sentence.contains("雨")||sentence.contains("水")){
                condition.append("\"rain\",");
            }
            if (sentence.contains("风")){
                condition.append("\"wind\",");
            }
            if (sentence.contains("云")){
                condition.append("\"cloud\",");
            }
            if (sentence.contains("温")){
                condition.append("\"temperature\",");
            }
            if (sentence.contains("湿")){
                condition.append("\"humidity\",");
            }
            if (sentence.contains("压")){
                condition.append("\"pressure\",");
            }
            if (condition.toString().equals("")){
                condition.append("\"wind\", \"rain\", \"cloud\", \"temperature\", \"pressure\", \"humidity\"");
            }else {
                condition.delete(condition.length()-1,condition.length());//删除逗号
            }

//            System.out.println(condition);
            String requestUrl = "http://192.168.2.63:12101/env-scene/weather/queryAreaWeather";
            String jsonInputString = "{\"rectangle\": {\"maxLat\": " + area.get(0) + ", \"maxLon\": " + area.get(1) + ", \"minLat\": " + area.get(2) + ", \"minLon\": " + area.get(3) + "}, \"time\": \"" + time + "\", \"typeList\": [" + condition + "]}";
            try {
                URL url = new URL(requestUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();

                // 设置请求方法和请求头
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "application/json; utf-8");
                connection.setRequestProperty("Accept", "application/json");
                connection.setDoOutput(true);

                // 发送JSON数据
                try(OutputStream os = connection.getOutputStream()) {
                    byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                }

                // 读取响应
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { // success
                    try(BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                        StringBuilder response = new StringBuilder();
                        String responseLine;
                        while ((responseLine = br.readLine()) != null) {
                            response.append(responseLine.trim());
                        }
//                        System.out.println("Response Body :: " + response.toString());
                        JSONObject jsonObject = new JSONObject(response.toString());
                        JSONArray dataArray = jsonObject.getJSONArray("data");

                        double /*max, min, */sum;
                        for (int i = 0; i < dataArray.length(); i++) {
                            JSONObject dataObject = dataArray.getJSONObject(i);
                            String dataType = dataObject.getString("type");
                            JSONArray data = new JSONArray(dataObject.getString("data"));

                            switch (dataType) {
                                case "wind" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的风力数据。\n");
                                        break;
                                    }
                                    double windU10m, windV10m, squareSum;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject windData = data.getJSONObject(j);
                                        windU10m = windData.getDouble("windU10m");
                                        windV10m = windData.getDouble("windV10m");
                                        squareSum = windU10m * windU10m + windV10m * windV10m;
                                        squareSum = Math.sqrt(squareSum);
//                                        max = Math.max(max, squareSum);
//                                        min = Math.min(min, squareSum);
                                        sum += squareSum;
                                    }
                                    result.append("该区域风力平均值为：").append(String.format("%.1f", sum / data.length()))/*.append("m/s，最大值为：").append(max).append("m/s，最小值为：").append(min)*/.append("m/s。\n");
                                }
                                case "rain" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的降雨量数据。\n");
                                        break;
                                    }
                                    double totalPrecipitation;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject rainData = data.getJSONObject(j);
                                        totalPrecipitation = rainData.getDouble("totalPrecipitation");
//                                        max = Math.max(max, totalPrecipitation);
//                                        min = Math.min(min, totalPrecipitation);
                                        sum += totalPrecipitation;
                                    }
                                    result.append("该区域降雨量平均值为：").append(String.format("%.2f", sum / data.length()))/*.append("mm，最大值为：").append(max).append("mm，最小值为：").append(min)*/.append("mm。\n");
                                }
                                case "cloud" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的云量数据。\n");
                                        break;
                                    }
                                    double lowCloudCover, mediumCloudCover, highCloudCover;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    double minLow = Double.MAX_VALUE, maxLow = Double.MIN_VALUE, sumLow = 0.0, minHigh = Double.MAX_VALUE, maxHigh = Double.MIN_VALUE, sumHigh = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject cloudData = data.getJSONObject(j);
                                        lowCloudCover = cloudData.getDouble("lowCloudCover");
//                                        maxLow = Math.max(max, lowCloudCover);
//                                        minLow = Math.min(min, lowCloudCover);
                                        sumLow += lowCloudCover;
                                        mediumCloudCover = cloudData.getDouble("mediumCloudCover");
//                                        max = Math.max(max, mediumCloudCover);
//                                        min = Math.min(min, mediumCloudCover);
                                        sum += mediumCloudCover;
                                        highCloudCover = cloudData.getDouble("highCloudCover");
//                                        maxHigh = Math.max(max, highCloudCover);
//                                        minHigh = Math.min(min, highCloudCover);
                                        sumHigh += highCloudCover;
                                    }
                                    result.append("该区域高层云云量平均值为：").append(String.format("%.2f", sumHigh / data.length()))/*.append("m/s，最大值为：").append(maxLow).append("m/s，最小值为：").append(minLow)*/.append("。\n");
                                    result.append("该区域中层云云量平均值为：").append(String.format("%.2f", sum / data.length()))/*.append("m/s，最大值为：").append(max).append("m/s，最小值为：").append(min)*/.append("。\n");
                                    result.append("该区域低层云云量平均值为：").append(String.format("%.2f", sumLow / data.length()))/*.append("m/s，最大值为：").append(maxHigh).append("m/s，最小值为：").append(minHigh)*/.append("。\n");
                                }
                                case "temperature" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的温度数据。\n");
                                        break;
                                    }
                                    double temperature2m;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject temperatureData = data.getJSONObject(j);
                                        temperature2m = temperatureData.getDouble("temperature2m") - 273.15;
//                                        max = Math.max(max, temperature2m);
//                                        min = Math.min(min, temperature2m);
                                        sum += temperature2m;
                                    }
                                    result.append("该区域温度平均值为：").append(String.format("%.1f", sum / data.length()))/*.append("℃，最大值为：").append(max).append("℃，最小值为：").append(min)*/.append("℃。\n");
                                }
                                case "pressure" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的大气压数据。\n");
                                        break;
                                    }
                                    double surfacePressure;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject pressureData = data.getJSONObject(j);
                                        surfacePressure = pressureData.getDouble("surfacePressure") / 1000;
//                                        max = Math.max(max, surfacePressure);
//                                        min = Math.min(min, surfacePressure);
                                        sum += surfacePressure;
                                    }
                                    result.append("该区域大气压平均值为：").append(String.format("%.1f", sum / data.length()))/*.append("kpa，最大值为：").append(max).append("kpa，最小值为：").append(min)*/.append("kpa。\n");
                                }
                                case "humidity" -> {
                                    if (data.toString().equals("[]")){
                                        result.append("数据库中没有该时间该区域的湿度数据。\n");
                                        break;
                                    }
                                    double relativeHumidity;
//                                    max = Double.MIN_VALUE;
//                                    min = Double.MAX_VALUE;
                                    sum = 0.0;
                                    for (int j = 0; j < data.length(); j++) {
                                        JSONObject humidityData = data.getJSONObject(j);
                                        relativeHumidity = humidityData.getDouble("relativeHumidity");
//                                        max = Math.max(max, relativeHumidity);
//                                        min = Math.min(min, relativeHumidity);
                                        sum += relativeHumidity;
                                    }
                                    result.append("该区域湿度值平均值为：").append(String.format("%.1f", sum / data.length()))/*.append("%，最大值为：").append(max).append("%，最小值为：").append(min)*/.append("%。\n");
                                }
                            }
                        }
                    }
                } else {
                    System.out.println("POST request not worked");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {//水文查询
            String jsonInputString = "{\"date\": \"" + time + "\", \"latitudeScope\": ["+ area.get(2) + "," + area.get(0) + "], \"longitudeScope\": [" + area.get(3) + "," + area.get(1) + "]}";
            String requestUrl;
            String response;

            if ((!sentence.contains("浪"))&&(!sentence.contains("温"))&&(!sentence.contains("盐"))&&(!sentence.contains("地"))){
                sentence = "浪温盐地";
            }
            if (sentence.contains("浪")){
                requestUrl = "http://192.168.2.63:12101/env-scene/hydrologicalData/querySeaTemperatureByArea";
                response = WaterDataset(jsonInputString, requestUrl);
                if (response.contains("POST request not worked")){
                    return "数据库接口未成功调用";
                }
                result.append("该区域的平均浪高：").append(response).append("m").append("。\n");
            }
            if (sentence.contains("温")){
                requestUrl = "http://192.168.2.63:12101/env-scene/hydrologicalData/querySeaTemperatureByArea";
                response = WaterDataset(jsonInputString, requestUrl);
                if (response.contains("POST request not worked")){
                    return "数据库接口未成功调用";
                }
                result.append("该区域的平均海水温度：").append(response).append("℃").append("。\n");
            }
            if (sentence.contains("盐")){
                requestUrl = "http://192.168.2.63:12101/env-scene/hydrologicalData/querySeaSalinityByArea";
                response = WaterDataset(jsonInputString, requestUrl);
                if (response.contains("POST request not worked")){
                    return "数据库接口未成功调用";
                }
                result.append("该区域的平均海水盐度：").append(response).append("‰").append("。\n");
            }
            if (sentence.contains("地")){
                requestUrl = "http://192.168.2.63:12101/env-scene/hydrologicalData/querySubmarineTopographyByArea";
                response = WaterDataset(jsonInputString, requestUrl);
                if (response.contains("POST request not worked")){
                    return "数据库接口未成功调用";
                }
                result.append("该区域的平均海水深度：").append(response);
            }
        }
        return result.toString();
    }

    /**
     * 查水文数据库，四个参数的查询接口不一样，但是入参一样
     *
     * @param jsonInputString 区域
     * @param requestUrl 接口
     * @return 结果
     */
    private static String WaterDataset(String jsonInputString, String requestUrl) {
        try {
            URL url = new URL(requestUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; utf-8");
            connection.setRequestProperty("Accept", "*/*");
            connection.setDoOutput(true);

            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
                os.write(input, 0, input.length);
            }
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { // success
                try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                    StringBuilder response = new StringBuilder();
                    StringBuilder result = new StringBuilder();
                    String responseLine;
                    while ((responseLine = br.readLine()) != null) {
                        response.append(responseLine.trim());
                    }
//                    System.out.println("Response Body :: " + response.toString());
                    JSONObject jsonObject = new JSONObject(response.toString());
                    if (jsonObject.getString("message").contains("暂无数据")){
                        result.append("数据库中暂无相应数据");
                    }
                    else {
                        JSONObject dataObject = jsonObject.getJSONObject("data");
                        JSONArray paramArray = dataObject.getJSONArray("param");
                        ArrayList<Double> value = avg(paramArray);
                        result/*.append("平均值为：")*/.append(value.get(0))/*.append("，最大值为：").append(value.get(1)).append("，最小值为：").append(value.get(2))*/;
                    }
                    return result.toString();
                }
            }
            else {
                System.out.println("POST request not worked");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "POST request not worked";
    }

    private static ArrayList<Double> avg(JSONArray array){
        double sum = 0;
//        double max = Double.MIN_VALUE;
//        double min = Double.MAX_VALUE;
        ArrayList<Double> result = new ArrayList<>();
        for (int i = 0; i < array.length(); i++) {
            sum += array.getDouble(i);
//            max = Math.max(array.getDouble(i), max);
//            min = Math.min(array.getDouble(i), min);
        }
        result.add(Math.round((array.length() > 0 ? sum / array.length() : 0) * 10.0) / 10.0);
//        result.add(max);
//        result.add(min);
        return result;
    }

//    public static void main(String[] args) {
//        ArrayList<Double> area = new ArrayList<>();
//        // 列表顺序：最大纬度，最大经度，最小纬度，最小经度
//        area.add(.5);
//        area.add(.5);
//        area.add(0.0);
//        area.add(0.0);
////        气象：只有2024.1整个月的数据
//        System.out.println(SearchDataBase("2024-01-01", area, 0, ""));//0类型，气象(只有1月的)
////        水文：只有2024.10.1当天的数据
//        System.out.println(SearchDataBase("2024-10-01", area, 1, ""));//0类型，水文
//    }
}